


import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.Set;

import org.apache.log4j.Logger;

import com.mango.http.AppSetting;
import com.mango.http.HttpServerInboundHandler2;
import com.mango.http.IocFactory;
import com.mango.http.ReqKey;
import com.mango.http.util.Constant;
import com.xiaoleilu.hutool.util.ClassUtil;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.stream.ChunkedWriteHandler;

public class HttpServer {
	public Logger log = Logger.getLogger(getClass());
	
	public static String contentPath = "/WebContent";
	
	private final int port;

	public HttpServer(int port) {
		this.port = port;
	}

	public void start() throws Exception {
		EventLoopGroup bossGroup = new NioEventLoopGroup(); // (1)  
        EventLoopGroup workerGroup = new NioEventLoopGroup();  
        try {  
            ServerBootstrap b = new ServerBootstrap(); // (2)  
            b.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 3000);//设置超时时间
            b.group(bossGroup, workerGroup);
            b.channel(NioServerSocketChannel.class); // (3)设置异步处理方式
            b.childHandler(new ChannelInitializer<SocketChannel>() { // (4)  
                                public void initChannel(SocketChannel ch) throws Exception {  
                                    // server端发送的是httpResponse，所以要使用HttpResponseEncoder进行编码  
                                    //ch.pipeline().addLast(new HttpResponseEncoder());  
                                    // server端接收到的是httpRequest，所以要使用HttpRequestDecoder进行解码  
                                    //ch.pipeline().addLast(new HttpRequestDecoder()); 
                                    ch.pipeline().addLast(new HttpServerCodec());
                                    ch.pipeline().addLast(new HttpObjectAggregator(65536));
                                    ch.pipeline().addLast(new ChunkedWriteHandler());
                                    //ch.pipeline().addLast(new HttpStaticFileServerHandler());
                                    ch.pipeline().addLast(new HttpServerInboundHandler2());  
                                }  
                            });
            b.option(ChannelOption.SO_BACKLOG, 128); // (5)  
            b.childOption(ChannelOption.SO_KEEPALIVE, true); // (6)  
            //加载注解，组装请求类容器
            initReqKey();
            ChannelFuture f = b.bind(port).sync(); // (7)  
            log.info("http server start at "+port);
            f.channel().closeFuture().sync();  
        } finally {  
            workerGroup.shutdownGracefully();  
            bossGroup.shutdownGracefully();  
        }  
	}
	/**
	 * 扫描ReqKey注解
	 */
	private void initReqKey() {
		Set<Class<?>> set = ClassUtil.scanPackageByAnnotation(AppSetting.app.getStr("app.scan"), ReqKey.class);
		List<String> objMethodOutList = Arrays.asList(AppSetting.app.getStr("app.method.object.out").split(","));
		for(Class<?> t : set){
			ReqKey rk = t.getAnnotation(ReqKey.class);
			String key = rk.value();//请求的key
			Method[] ms = t.getMethods();
			for(Method m : ms){
				if(!objMethodOutList.contains(m.getName())){
					String reqKey = key + "/" + m.getName();
					if(key.equals("/")){
						reqKey = reqKey.replace("//", "/");
					}
					IocFactory.reqKeyMap.put(reqKey, t.getName()+"#"+m.getName());
				}
			}
			System.out.println(IocFactory.reqKeyMap.toString());
		}
	}

	public static void main(String[] args) throws Exception {
		if(args.length>0){
			System.out.println("参数："+args[0]);
			String arg  = args[0];
			if(arg!=null && arg.equals("productModel")){
				//产品模式
				Constant.contextPath = "";
			}
		}
		new HttpServer(AppSetting.app.getInt("app.port")).start();
	}

}